﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WMPLib;
using WMPRemote;

namespace WmpRemoteServer
{
    class WindowsMediaPlayerController
    {
        private WindowsMediaPlayer wmp;

        private IWMPPlaylist currentPlaylist;
        private int currentPosition;
        private int duration;
        private string title;
        private bool mute;
        private int volume;
        private bool repeat;
        private bool shuffle;
        private int status;
        public delegate void WMPRemoteEvent(string info);
        public event WMPRemoteEvent InfoEvent;

        public WindowsMediaPlayerController()
        {
            RemotedWindowsMediaPlayer player = new RemotedWindowsMediaPlayer();
            player.CreateControl();
            wmp = player.GetOcx() as WindowsMediaPlayer;
            updateInfoAndAddEvents();
        }

        private void updateInfoAndAddEvents()
        {
            currentPosition = (int) wmp.controls.currentPosition;
            try
            {
                duration = (int) wmp.currentMedia.duration;
                title = wmp.currentMedia.name;
                currentPlaylist = wmp.currentPlaylist;
            }
            catch (Exception e)
            {
                //No Media in the playlist
                duration = 0;
                title = "WMP is not Running";
            }
            mute = wmp.settings.mute;
            volume = wmp.settings.volume;
            repeat = wmp.settings.getMode("loop");
            shuffle = wmp.settings.getMode("shuffle");
            status = 3;
            string temp = wmp.playState.ToString();
            if (temp.Equals("wmppsPlaying"))
                status = 1;
            else if (temp.Equals("wmppsPaused"))
                status = 2;
            wmp.CurrentItemChange += new _WMPOCXEvents_CurrentItemChangeEventHandler(wmp_CurrentItemChange);
            wmp.PlayStateChange += new _WMPOCXEvents_PlayStateChangeEventHandler(wmp_PlayStateChange);
            wmp.ModeChange += new _WMPOCXEvents_ModeChangeEventHandler(wmp_ModeChange);
            wmp.PositionChange += new _WMPOCXEvents_PositionChangeEventHandler(wmp_PositionChange);
            wmp.CurrentPlaylistChange += new _WMPOCXEvents_CurrentPlaylistChangeEventHandler(wmp_CurrentPlaylistChange);
        }

        private void wmp_CurrentItemChange(object item)
        {
            duration = (int) wmp.currentMedia.duration;
            title = wmp.currentMedia.name;
            sendInfoUpdate();
        }

        private void wmp_PlayStateChange(int newState)
        {
            int temp = status;
            switch (newState)
            {
                case 1:    // Stopped
                    status = 3;
                    break;

                case 2:    // Paused
                    status = 2;
                    break;

                case 3:    // Playing
                    status = 1;
                    break;
            }
            if (temp != status)
                sendInfoUpdate();
        }

        private void wmp_ModeChange(string ModeName, bool NewValue)
        {
            if (ModeName.Equals("loop"))
            {
                repeat = NewValue;
                sendInfoUpdate();
            }
            else if (ModeName.Equals("shuffle"))
            {
                shuffle = NewValue;
                sendInfoUpdate();
            }
        }
        private void wmp_PositionChange(double oldPosition, double newPosition)
        {
            sendInfoUpdate();
        }

        private void wmp_CurrentPlaylistChange(WMPPlaylistChangeEventType change)
        {
            try
            {
                switch (change)
                {
                    case WMPLib.WMPPlaylistChangeEventType.wmplcNameChange:
                    case WMPLib.WMPPlaylistChangeEventType.wmplcMove:
                    case WMPLib.WMPPlaylistChangeEventType.wmplcDelete:
                    case WMPLib.WMPPlaylistChangeEventType.wmplcInsert:
                    case WMPLib.WMPPlaylistChangeEventType.wmplcAppend:
                        currentPlaylist = wmp.currentPlaylist;
                        InfoEvent(getCurrentPlaylistToSend());
                        break;
                }
            }
            catch (Exception e)
            {
                Console.Write(e);//Either wmp is busy or it's not running
            }
        }

        private string getCurrentPlaylistToSend()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("playlist;");
            sb.Append(currentPlaylist.name + ";");
            for (int i = 0; i < currentPlaylist.count; i++)
            {
                sb.Append(currentPlaylist.get_Item(i).name + ";");
            }
            sb.Append("<EOS>");
            return sb.ToString();
        }

        private bool comparePlaylist(IWMPPlaylist newPlaylist)
        {
            if (!currentPlaylist.name.Equals(newPlaylist.name))
                return true;
            if (currentPlaylist.count != newPlaylist.count)
                return true;
            string currentName;
            string newName;
            for (int i = 0; i < currentPlaylist.count; i++)
            {
                currentName = currentPlaylist.get_Item(i).name;
                newName = newPlaylist.get_Item(i).name;
                if (!currentName.Equals(newName))
                    return true;
            }
            return false;
        }

        public string getStringToSend()
        {
            string info = status + ";" + repeat + ";" + shuffle + ";" + mute + ";";
            info += volume + ";" + title + ";" + currentPosition + ";" + duration;
            info += ";<EOS>";
            return info;
        }

        private void sendInfoUpdate()
        {
            currentPosition = (int) wmp.controls.currentPosition;
            mute = wmp.settings.mute;
            volume = wmp.settings.volume;
            InfoEvent(getStringToSend());
        }

        public void Mute(bool mute)
        {
            if (this.mute != mute)
            {
                try
                {
                    wmp.settings.mute = mute;
                    this.mute = mute;
                }
                catch (Exception e)
                {
                    Console.Write(e);//Either wmp is busy or it's not running
                }
            }
        }

        public void Loop(bool loop)
        {
            if (repeat != loop)
            {
                try
                {
                    wmp.settings.setMode("loop", loop);
                    repeat = loop;
                }
                catch (Exception e)
                {
                    Console.Write(e);//Either wmp is busy or it's not running
                }
            }
        }

        public void Shuffle(bool shuffle)
        {
            if (this.shuffle != shuffle)
            {
                try
                {
                    wmp.settings.setMode("shuffle", shuffle);
                    this.shuffle = shuffle;
                }
                catch (Exception e)
                {
                    Console.Write(e);//Either wmp is busy or it's not running
                }
            }
        }

        public void Volume(int volume)
        {
            if (this.volume != volume)
            {
                try
                {
                    wmp.settings.volume = volume;
                    this.volume = volume;
                }
                catch (Exception e)
                {
                    Console.Write(e);//Either wmp is busy or it's not running
                }
            }
        }

        private void CurrentPosition(int pos)
        {
            if (pos >= 0 && pos < duration)
                try
                {
                    wmp.controls.currentPosition = pos;
                }
                catch (Exception e)
                {
                    Console.Write(e);//Either wmp is busy or it's not running
                }
        }

        public void PlayPause()
        {
            if (status == 1)
                Pause();
            else
                Play();
        }

        private void Play()
        {
            try
            {
                wmp.controls.play();
            }
            catch (Exception e)
            {
                Console.Write(e);//Either wmp is busy or it's not running
            }
        }

        private void Pause()
        {
            try
            {
                wmp.controls.pause();
            }
            catch (Exception e)
            {
                Console.Write(e);//Either wmp is busy or it's not running
            }
        }

        public void Stop()
        {
            try
            {
                wmp.controls.stop();
            }
            catch (Exception e)
            {
                Console.Write(e);//Either wmp is busy or it's not running
            }
        }

        public void Next()
        {
            try
            {
                wmp.controls.next();
            }
            catch (Exception e)
            {
                Console.Write(e);//Either wmp is busy or it's not running
            }
        }

        public void Previous()
        {
            try
            {
                wmp.controls.previous();
            }
            catch (Exception e)
            {
                Console.Write(e);//Either wmp is busy or it's not running
            }
        }

        public void changeItemPlaying(int itemId)
        {
            try
            {
                if (itemId >= 0 && itemId < currentPlaylist.count)
                {
                    IWMPMedia m = currentPlaylist.get_Item(itemId);
                    wmp.controls.playItem(m);
                }
            }
            catch (Exception e)
            {
                Console.Write(e);//Either wmp is busy or it's not running
            }
        }

        public void CloseWMP()
        {
            wmp.CurrentItemChange -= new _WMPOCXEvents_CurrentItemChangeEventHandler(wmp_CurrentItemChange);
            wmp.PlayStateChange -= new _WMPOCXEvents_PlayStateChangeEventHandler(wmp_PlayStateChange);
            wmp.ModeChange -= new _WMPOCXEvents_ModeChangeEventHandler(wmp_ModeChange);
            wmp.PositionChange -= new _WMPOCXEvents_PositionChangeEventHandler(wmp_PositionChange);
            wmp.CurrentPlaylistChange -= new _WMPOCXEvents_CurrentPlaylistChangeEventHandler(wmp_CurrentPlaylistChange);
        }

        public void Commands(string data)
        {
            string[] info = data.Split(';');
            if (info.Length == 3)
                if (info[0].Equals("playlist"))
                {
                    if (info[1].Equals("get"))
                    {
                        InfoEvent(getCurrentPlaylistToSend());
                    }
                    else
                    {
                        changeItemPlaying(int.Parse(info[1]));
                    }
                }
                else if (info[0].Equals("playerInfo"))
                {
                    if(info[1].Equals("get"))
                    {
                        sendInfoUpdate();
                    }
                }
            if (info.Length == 9)
                command(info);

        }

        public void command(string[] info)
        {
            int tempStatus = int.Parse(info[0]);
            if (tempStatus != 0)
                status = tempStatus;
            bool loop = bool.Parse(info[1]);
            bool shuffle = bool.Parse(info[2]);
            bool mute = bool.Parse(info[3]);
            int volume = int.Parse(info[4]);
            string title = info[5];
            int pos = int.Parse(info[6]);
            int duration = int.Parse(info[7]);

            switch (tempStatus)
            {
                case 1:
                    Play();
                    break;
                case 2:
                    Pause();
                    break;
                case 3:
                    Stop();
                    break;
                case 4:
                    Next();
                    break;
                case 5:
                    Previous();
                    break;
            }
            Loop(loop);
            Shuffle(shuffle);
            Mute(mute);
            Volume(volume);
            CurrentPosition(pos);
        }

    }
}
